package com.dddpeter.app.util;

import com.dddpeter.app.entity.Article;
import com.dddpeter.app.service.IdGeneratorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * ID唯一性测试工具
 * 用于验证ID生成器在多线程环境下的唯一性
 */
@Component
public class IdUniquenessTest {
    
    @Autowired
    private IdGeneratorService idGeneratorService;
    
    /**
     * 测试文章ID的唯一性
     * @param threadCount 线程数量
     * @param idCountPerThread 每个线程生成的ID数量
     */
    public void testArticleIdUniqueness(int threadCount, int idCountPerThread) {
        System.out.println("开始测试文章ID唯一性...");
        System.out.println("线程数: " + threadCount + ", 每线程ID数: " + idCountPerThread);
        
        Set<Long> generatedIds = ConcurrentHashMap.newKeySet();
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        CountDownLatch latch = new CountDownLatch(threadCount);
        
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < threadCount; i++) {
            final int threadIndex = i;
            executor.submit(() -> {
                try {
                    for (int j = 0; j < idCountPerThread; j++) {
                        Long id = idGeneratorService.generateArticleId();
                        generatedIds.add(id);
                        
                        if (j % 100 == 0) {
                            System.out.println("线程 " + threadIndex + " 已生成 " + j + " 个ID");
                        }
                    }
                } catch (Exception e) {
                    System.err.println("线程 " + threadIndex + " 发生异常: " + e.getMessage());
                } finally {
                    latch.countDown();
                }
            });
        }
        
        try {
            latch.await();
            long endTime = System.currentTimeMillis();
            
            int totalExpected = threadCount * idCountPerThread;
            int totalGenerated = generatedIds.size();
            
            System.out.println("测试完成!");
            System.out.println("期望生成ID数量: " + totalExpected);
            System.out.println("实际生成ID数量: " + totalGenerated);
            System.out.println("是否有重复: " + (totalExpected != totalGenerated ? "是" : "否"));
            System.out.println("总耗时: " + (endTime - startTime) + "ms");
            System.out.println("平均每个ID耗时: " + ((endTime - startTime) / (double) totalGenerated) + "ms");
            
            if (totalExpected != totalGenerated) {
                System.err.println("警告: 检测到ID重复!");
            } else {
                System.out.println("✓ 所有ID都是唯一的!");
            }
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.err.println("测试被中断: " + e.getMessage());
        } finally {
            executor.shutdown();
        }
    }
    
    /**
     * 测试用户ID的唯一性
     */
    public void testUserIdUniqueness(int threadCount, int idCountPerThread) {
        System.out.println("开始测试用户ID唯一性...");
        System.out.println("线程数: " + threadCount + ", 每线程ID数: " + idCountPerThread);
        
        Set<Long> generatedIds = ConcurrentHashMap.newKeySet();
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        CountDownLatch latch = new CountDownLatch(threadCount);
        
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < threadCount; i++) {
            final int threadIndex = i;
            executor.submit(() -> {
                try {
                    for (int j = 0; j < idCountPerThread; j++) {
                        Long id = idGeneratorService.generateUserId();
                        generatedIds.add(id);
                        
                        if (j % 100 == 0) {
                            System.out.println("线程 " + threadIndex + " 已生成 " + j + " 个ID");
                        }
                    }
                } catch (Exception e) {
                    System.err.println("线程 " + threadIndex + " 发生异常: " + e.getMessage());
                } finally {
                    latch.countDown();
                }
            });
        }
        
        try {
            latch.await();
            long endTime = System.currentTimeMillis();
            
            int totalExpected = threadCount * idCountPerThread;
            int totalGenerated = generatedIds.size();
            
            System.out.println("测试完成!");
            System.out.println("期望生成ID数量: " + totalExpected);
            System.out.println("实际生成ID数量: " + totalGenerated);
            System.out.println("是否有重复: " + (totalExpected != totalGenerated ? "是" : "否"));
            System.out.println("总耗时: " + (endTime - startTime) + "ms");
            
            if (totalExpected != totalGenerated) {
                System.err.println("警告: 检测到ID重复!");
            } else {
                System.out.println("✓ 所有ID都是唯一的!");
            }
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.err.println("测试被中断: " + e.getMessage());
        } finally {
            executor.shutdown();
        }
    }
    
    /**
     * 快速测试
     */
    public void quickTest() {
        System.out.println("=== 快速ID唯一性测试 ===");
        testArticleIdUniqueness(5, 100);
        System.out.println();
        testUserIdUniqueness(5, 100);
    }
    
    /**
     * 压力测试
     */
    public void stressTest() {
        System.out.println("=== 压力测试 ===");
        testArticleIdUniqueness(10, 500);
        System.out.println();
        testUserIdUniqueness(10, 500);
    }
}
